Skip to content

Add imagemagick-heic to the Alpine variants - #1015

Open
LeoFidjeland wants to merge 1 commit into
docker-library:masterfrom
LeoFidjeland:alpine-imagemagick-heic
Open

LeoFidjeland wants to merge 1 commit into
docker-library:masterfrom
LeoFidjeland:alpine-imagemagick-heic

Conversation

@LeoFidjeland

Copy link
Copy Markdown

Alpine packages ImageMagick's coders as separate subpackages, and the base imagemagick
package ships none of them. So on the Alpine images Imagick::queryFormats('AVIF') is
empty, WP_Image_Editor_Imagick::supports_mime_type('image/avif') returns false, and
_wp_image_editor_choose() falls back to WP_Image_Editor_GD.

That fallback is lossy. GD's imageavif() discards the ICC profile and tags output as
sRGB, so uploads carrying Adobe RGB or Display P3 profiles get reinterpreted as sRGB and
render visibly desaturated. Nothing errors — the AVIF files are produced successfully,
just without their colour information — which makes this easy to run into without
realising. The Debian variants are unaffected, because there libmagickcore links libheif
directly.

This is the Alpine counterpart to #996 (fixed for Debian in #997). The difference is that #996 was decode-only
support failing loudly at encode time (no encode delegate for this image format 'AVIF'),
whereas here Imagick has no AVIF support at all, so it fails the editor-capability check
and WordPress quietly uses a different editor.

Before

$ docker run --rm wordpress:fpm-alpine php -r 'var_dump(Imagick::queryFormats("AVIF"));'
array(0) {
}

$ docker run --rm wordpress:fpm-alpine sh -c 'ls /usr/lib/ImageMagick-*/modules-*/coders/ | grep -c heic'
0

After

Built from latest/php8.3/fpm-alpine with this change:

$ docker run --rm wp-heic-test php -r 'var_dump(Imagick::queryFormats("AVIF"));'
array(1) {
  [0]=>
  string(4) "AVIF"
}

AVIF encodes, and the profile survives a JPEG → AVIF conversion:

src icc: 560 bytes (Adobe RGB (1998))
out icc: 560 bytes

Measured mean saturation on a real Adobe RGB photograph: source JPEG 44.25%, Imagick AVIF
44.41%. The GD output the images currently produce is visibly lower.

On size

The image grows 3 MB, from 310.4 MB to 313.4 MB.

AVIF encoding needs no new heavy dependency: libavif, aom-libs and libdav1d are
already in the image for GD's --with-avif, and imagemagick-heic brings libheif-aom
with it. The added weight is libheif itself (1.6 MB), libde265 (0.6 MB) and a few small
plugin shims; the ImageMagick coder module is 66 KiB.

I initially also added libheif-x265 for HEVC parity with the Debian variants after #997,
but dropped it - it is 6.8 MB on its own, more than twice the cost of this fix, and HEIC
encoding is not what breaks here. Happy to add it in a follow-up if that parity is wanted.

Dockerfile.template was edited and ./apply-templates.sh run; the 8 generated
fpm-alpine Dockerfiles are the only other files changed.

Alpine packages ImageMagick's coders separately and the base "imagemagick"
package ships none of them, so on the Alpine images
Imagick::queryFormats('AVIF') is empty,
WP_Image_Editor_Imagick::supports_mime_type('image/avif') returns false, and
_wp_image_editor_choose() falls back to WP_Image_Editor_GD.

That fallback is lossy: GD's imageavif() discards the ICC profile and tags the
output sRGB, so uploads carrying Adobe RGB or Display P3 profiles get
reinterpreted as sRGB and render desaturated. Nothing errors, which makes it
easy to miss - the AVIF files are produced successfully, just without their
colour information.

AV1 encoding needs no new dependency: libheif-aom comes in with
imagemagick-heic, and libavif/aom-libs are already present for GD's
--with-avif. The image grows 3 MB, from 310.4 MB to 313.4 MB.

Verified against latest/php8.3/fpm-alpine: a JPEG carrying a 560-byte Adobe RGB
profile round-trips through AVIF with the profile intact.
@yosifkit

Copy link
Copy Markdown
Member

This seems fine to me. Related to #919 that added AVIF support for gd.

You mention that adding libheif-x265 was a bit too large, but are there other imagemagick* packages in Alpine that would make sense to include (i.e., are important/necessary to core WP functionality)?

@tianon

tianon commented Sep 22, 2026

Copy link
Copy Markdown
Member

Here's a full diff of current Debian vs current Alpine:

$ diff -u <(docker run --rm wordpress:fpm php -r 'echo join("\n", Imagick::queryFormats());') <(docker run --rm wordpress:fpm-alpine php -r 'echo join("\n", Imagick::queryFormats());')
--- /dev/fd/63	2026-09-22 16:36:36.660507132 -0700
+++ /dev/fd/62	2026-09-22 16:36:36.664507166 -0700
@@ -1,22 +1,19 @@
-3FR
 3G2
 3GP
 AAI
 AI
 APNG
 ART
-ARW
+ASE
+ASEPRITE
 ASHLAR
-AVCI
 AVI
-AVIF
 AVS
 BAYER
 BAYERA
 BGR
 BGRA
 BGRO
-BIE
 BMP
 BMP2
 BMP3
@@ -30,20 +27,15 @@
 CLIP
 CMYK
 CMYKA
-CR2
-CR3
-CRW
 CUBE
 CUR
 CUT
 DATA
 DCM
-DCR
-DCRAW
 DCX
 DDS
 DFONT
-DNG
+DOT
 DPX
 DXT1
 DXT5
@@ -57,11 +49,9 @@
 EPT
 EPT2
 EPT3
-ERF
 FARBFELD
 FAX
 FF
-FFF
 FILE
 FITS
 FL32
@@ -78,10 +68,9 @@
 GRAY
 GRAYA
 GROUP4
+GV
 HALD
 HDR
-HEIC
-HEIF
 HISTOGRAM
 HRZ
 HTM
@@ -89,9 +78,9 @@
 HTTP
 HTTPS
 ICB
+ICN
 ICO
 ICON
-IIQ
 INFO
 INLINE
 IPL
@@ -99,8 +88,6 @@
 ISOBRL6
 J2C
 J2K
-JBG
-JBIG
 JNG
 JNX
 JP2
@@ -112,8 +99,6 @@
 JPS
 JPT
 JSON
-K25
-KDC
 KERNEL
 LABEL
 M2V
@@ -123,28 +108,21 @@
 MASK
 MAT
 MATTE
-MDC
-MEF
 MIFF
 MKV
 MNG
 MONO
-MOS
 MOV
 MP4
 MPC
 MPEG
 MPG
 MPO
-MRW
 MSL
 MTV
 MVG
-NEF
-NRW
 NULL
 ORA
-ORF
 OTB
 OTF
 PAL
@@ -160,7 +138,6 @@
 PDB
 PDF
 PDFA
-PEF
 PES
 PFA
 PFB
@@ -192,9 +169,7 @@
 PWP
 QOI
 RADIAL-GRADIENT
-RAF
 RAS
-RAW
 RGB
 RGB565
 RGBA
@@ -202,22 +177,16 @@
 RGF
 RLA
 RLE
-RMF
-RW2
-RWL
 SCR
 SCT
+SF3
 SFW
 SGI
 SHTML
 SIX
 SIXEL
 SPARSE-COLOR
-SR2
-SRF
-SRW
 STEGANO
-STI
 STRIMG
 SUN
 TEXT
@@ -241,13 +210,13 @@
 VIFF
 VIPS
 VST
+WBINFO
 WBMP
 WEBM
 WEBP
 WMV
 WPG
 X
-X3F
 XBM
 XC
 XCF

@tianon

tianon commented Sep 22, 2026

Copy link
Copy Markdown
Member

In general though, if all a user has to do in order to enable more of these is install packages, I'm honestly kind of inclined to leave them out of the Alpine variant -- size is the main reason it even exists to begin with.

@tianon

tianon commented Sep 22, 2026

Copy link
Copy Markdown
Member

To illustrate:

$ docker run --rm wordpress:fpm-alpine php -r 'var_dump(Imagick::queryFormats("AVIF"));'
array(0) {
}

$ docker run --rm wordpress:fpm-alpine sh -c 'apk add --no-cache --quiet imagemagick-heic && exec "$@"' -- php -r 'var_dump(Imagick::queryFormats("AVIF"));'
  * 
  * libheif installs only basic HEIC/HEVC and AVIF/AV1 *decoders* by default.
  * If you want to encode (edit) HEIC and AVIF images, you may need to install
  * libheif-x265 and libheif-rav1e (or libheif-aom), respectively. You can also
  * install libheif-plugins-all to get all encoders and decoders.
  * 
array(1) {
  [0]=>
  string(4) "AVIF"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants